﻿#ifndef TB_REFLECTION_VARIANT_HPP__
#define TB_REFLECTION_VARIANT_HPP__

#include <boost/atomic/atomic.hpp>
#include <boost/shared_ptr.hpp>

#include "tbcore/base/basic_types.hpp"
#include "tbcore/base/assert.hpp"
#include "tbcore/base/string/utf_string_conversions.hpp"
#include "tbcore/base/unique_id.hpp"
#include "tbcore/base/logging.hpp"

#include "tbcore/reflection/reflection_export.hpp"
#include "tbcore/reflection/reflection_fwd.hpp"
#include "tbcore/reflection/type_traits.hpp"
#include "tbcore/reflection/type_cast.hpp"
#include "tbcore/reflection/allocator.hpp"

#define TB_VALID_TYPE(t) (t > 0)
#define TB_INVALID_TYPE(t) (t <= 0)

TB_NAMESPACE_BEGIN

MSVC_PUSH_WARNING()
MSVC_DISABLE_WARNING(4800)
MSVC_DISABLE_WARNING(4789)

class TB_REFLECTION_API Variant {
public:
  // variant type
  enum {
    kNullType = 0,
    kBoolType,
    kInt8Type,
    kUint8Type,
    kInt16Type,
    kUint16Type,
    kInt32Type,
    kUint32Type,
    kInt64Type,
    kUint64Type,
    kFloatType,
    kDoubleType,
    kDurationType,
    kDatetimeType,
    kStringType,
    kObjectIdType,
    kBinaryType,
    kEnumType,
    kVariantType,
    kUserType,
  };

  // type flag
  enum {
    kComplexTypeFlag,
    kValueTypeFlag,
    kPointerTypeFlag,
    kReferenceTypeFlag,
    kSharedPtrTypeFlag,
    kRefSharedPtrTypeFlag
  };

  // data flag
  enum {
    kNullDataFlag,
    kObjectDataFlag,
    kMapDataFlag,
    kPairDataFlag,
    kArrayDataFlag,
  };

  Variant();
  Variant(uint32 typeId, uint8 typeFlag, uint8 dataFlag);
  Variant(bool b);
  Variant(int8 i8);
  Variant(uint8 u8);
  Variant(int16 i16);
  Variant(uint16 u16);
  Variant(int32 i32);
  Variant(uint32 u32);
  Variant(int64 i64);
  Variant(uint64 u64);
  Variant(float f);
  Variant(double d);
  Variant(const std::string& str);
  Variant(const string16& str);
  Variant(const char* str);
  Variant(const char* str, uint32 len);
  Variant(const Duration& d);
  Variant(const DateTime& d);
	Variant(const UniqueId& oid);
  Variant(const Variant& rhs);
  Variant(Variant&& rhs);
  Variant& operator=(const Variant& rhs);
  Variant& operator=(Variant&& rhs);
  ~Variant();

  void *Data() const;
  // ensure exlusive
  void *Detach();
  Variant Copy() const;
  void Assign(Variant& rhs);
  void Destroy();
	int Compare(const Variant& rhs) const;
  _STD string ToString() const;

  TB_INLINE uint32 TypeId() const { return data_.typeId; }
  TB_INLINE uint8 TypeFlag() const {return data_.typeFlag; }
  TB_INLINE uint8 DataFlag() const {return data_.dataFlag; }
  TB_INLINE bool IsNull() const { return kNullType == data_.typeId && kNullDataFlag == data_.dataFlag; }
  TB_INLINE const void* ConstData() const { return Data(); }
  TB_INLINE VoidPtr GetPtr() const { return *(static_cast<VoidPtr *>(data_.value.ptr)); }
  TB_INLINE void* DataPtr() const { 
    return (IsRefSharedPtr() || IsSharedPtr()) ? (static_cast<VoidPtr *>(data_.value.ptr))->get() : Data(); 
  }

	TB_INLINE bool IsReference() const { return data_.typeFlag == kReferenceTypeFlag;  }
  TB_INLINE bool IsSharedPtr() const { return data_.typeFlag == kSharedPtrTypeFlag; }
	TB_INLINE bool IsRefSharedPtr() const { return data_.typeFlag == kRefSharedPtrTypeFlag; }

  TB_INLINE bool IsNormValue() const { return data_.dataFlag == kNullDataFlag; }  
  TB_INLINE bool IsObject() const { return data_.dataFlag == kObjectDataFlag; }
  TB_INLINE bool IsPair() const { return data_.dataFlag == kPairDataFlag; }
  TB_INLINE bool IsArray() const { return data_.dataFlag == kArrayDataFlag; }
  TB_INLINE bool IsMap() const { return data_.dataFlag == kMapDataFlag; }
	TB_INLINE bool IsComplexType() const { return data_.typeFlag == kComplexTypeFlag; };

  bool IsBool() const;
  bool IsInt8() const;
  bool IsUInt8() const;
  bool IsInt16() const;
  bool IsUInt16() const;
  bool IsInt32() const;
  bool IsUInt32() const;
  bool IsInt64() const;
  bool IsUInt64() const;
  bool IsFloat() const;
  bool IsDouble() const;
	bool IsObjectId() const;
	bool IsUserType() const;
	bool IsBuildinType() const;
	bool IsSimpleType() const;

  bool GetBool() const;
  int8 GetInt8() const;
  uint8 GetUInt8() const;
  int16 GetInt16() const;
  uint16 GetUInt16() const;
  int32 GetInt32() const;
  uint32 GetUInt32() const;
  int64 GetInt64() const;
  uint64 GetUInt64() const;
  float GetFloat() const;
  double GetDouble() const;
	UniqueId GetObjectId() const;
  Variant *GetKey() const;
  Variant *GetValue() const;
	Variant **GetArray() const;
  struct Pair_T;
	Pair_T *GetMap() const;
  void Clear();
  uint32 Size() const;

  void PushBack(const Variant& val);
  void Insert(const Variant& key, const Variant& val);
	void SetPair(const Variant& key, const Variant& val);

  static Variant FromObject(VoidPtr d, uint32 typeId, reflection::Allocator* alloc);
  static Variant FromObject(void* d, uint32 typeId, reflection::Allocator* alloc);

  template <typename T, typename Enabled = void> struct
	FromValueImpl {
		static Variant From(const T& val) {
			uint32 fromId = GetVariantTypeId<T>(&val);
			TB_ASSERT(TB_VALID_TYPE(fromId));
			if (IsSimpleTypeId(fromId)) {
        Variant v(fromId, kValueTypeFlag, kNullDataFlag);
				*reinterpret_cast<T*>(&v.data_.value.num) = val;
        return v;
			} else if (const reflection::TypeInfo* info = reflection::GetTypeInfo(fromId)) {
				if (info->name.empty()) {
					_LWARNING() << typeid(T).name() << " not registered!";
				}
				if (reflection::ExtentInfo* ext = info->extInfo) {
          if (ext->firstType && ext->secondType) {
            Variant v(fromId, kComplexTypeFlag, kMapDataFlag);
						reflection::CollectionEnumerPtr itor = ext->iterator->Create(&val);
						while (itor->HasNext()) {
							Variant pv = itor->Next();
							TB_ASSERT(pv.IsPair());
							v.Insert(*pv.GetKey(), *pv.GetValue());
						}
            return v;
					} else if (ext->firstType) {
            Variant v(fromId, kComplexTypeFlag, kArrayDataFlag);
						reflection::CollectionEnumerPtr itor = ext->iterator->Create(&val);
						while (itor->HasNext()) {
							Variant pv = itor->Next();
							v.PushBack(pv);
						}
            return v;
					}
				} else {
          Variant v(fromId, kValueTypeFlag, kObjectDataFlag);
					v.AsObjectT()->alloc = info->operators.allocator;
					v.AsObjectT()->obj = v.AsObjectT()->alloc->Malloc(&val);
          return v;
				}
			} else {
				_LWARNING() << "unrecognized type";
			}
      return Variant();
		}
	};

 	template <typename T> struct
 	FromValueImpl< T, typename boost::enable_if<is_enum<T> >::type > {
 		static Variant From(const T& val) {
			Variant v(kEnumType, kValueTypeFlag, kNullDataFlag);
			v.data_.value.num.u32.u32 = static_cast<uint32>(val);
 			return v;
 		}
	};

	template <typename T, uint32 N> struct
	FromValueImpl < T[N] > {
		static Variant From(const T* val) {
			uint32 fromId = GetVariantTypeId<T[N]>();
			TB_ASSERT(TB_VALID_TYPE(fromId));
			Variant v(fromId, kComplexTypeFlag, kArrayDataFlag);
			for (uint32 i = 0; i < N; ++i) {
				v.PushBack(Variant::FromValue(val[i]));
			}
			return v;
		}
	};

	template <typename T>
	static Variant FromValue(const T& val) {
		return FromValueImpl<T>::From(val);
	}

  template <typename T>
  static Variant FromValue(const shared_ptr<T>& val) {
    uint32 fromId = GetVariantTypeId<T>(val.get());
    Variant v(fromId, kSharedPtrTypeFlag, kNullDataFlag);
    VoidPtr* vptr = (VoidPtr*)TB_OPTIMIZED_NEW_ARG(VoidPtr, val);
    v.data_.value.ptr = vptr;
    return v;
  }

  template <>
  static Variant FromValue(const Variant& val) {
    return Variant(val);
  }

  template <>
  static Variant FromValue(const Duration& val) {
    Variant v(kDurationType, kValueTypeFlag, kNullDataFlag);
    v.data_.value.num.i64 = val.TotalMilliseconds();
    return v;
  }

  template <>
  static Variant FromValue(const DateTime& val) {
    Variant v(kDatetimeType, kValueTypeFlag, kNullDataFlag);
    v.data_.value.num.i64 = val.TotalMilliseconds();
    return v;
  }

	template <>
	static Variant FromValue(const UniqueId& val) {
		Variant v(kObjectIdType, kValueTypeFlag, kNullDataFlag);
		v.AsObjectIdT()->oid = TB_OPTIMIZED_NEW_ARG(UniqueId, val);
		return v;
	}

  template <>
  static Variant FromValue(const std::string& val) {
    Variant v(kStringType, kValueTypeFlag, kNullDataFlag);
    v.AsStringT()->size = (uint32)val.size();
		v.AsStringT()->str = (char*)TB_OPTIMIZED_MALLOC(v.AsStringT()->size);
		memcpy(v.AsStringT()->str, val.c_str(), v.AsStringT()->size);
    return v;
  }

  template <>
  static Variant FromValue(const string16& val) {
    std::string str(UTF16ToUTF8(val));
    Variant v(kStringType, kValueTypeFlag, kNullDataFlag);
		v.AsStringT()->size = (uint32)str.size();
    v.AsStringT()->str = (char*)TB_OPTIMIZED_MALLOC(v.AsStringT()->size);
		memcpy(v.AsStringT()->str, str.c_str(), v.AsStringT()->size);
    return v;
  }

  template <typename _Ty1, typename _Ty2>
  static Variant FromValue(const std::pair<_Ty1, _Ty2>& val) {
		uint32 typeId = GetVariantTypeId<std::pair<_Ty1, _Ty2>>();
		TB_ASSERT(TB_VALID_TYPE(typeId));
		Variant v(typeId, kComplexTypeFlag, kPairDataFlag);
    v.AsPairT()->key = TB_OPTIMIZED_NEW_ARG(Variant, Variant::FromValue(val.first));
    v.AsPairT()->value = TB_OPTIMIZED_NEW_ARG(Variant, Variant::FromValue(val.second));
    return v;
  }

  template <typename T, typename Enabled = void> struct 
  ToValueImpl {
    static T Value(const Variant& val) {
			if (val.IsReference()) return T();

      TB_STATIC_ASSERT(!is_pointer<T>::value && !is_reference<T>::value, "");

      uint32 typeId = GetVariantTypeId<T>();
			TB_ASSERT(TB_VALID_TYPE(typeId));

			if (val.IsObjectId()) {
				TB_SMART_ASSERT(val.TypeId() == typeId && "object id can not convert to other type");
			}

      if (!val.IsNull()) {
				if (const reflection::TypeInfo* info = reflection::GetTypeInfo(typeId)) {
          if (val.IsArray() || val.IsMap()) {
						if (const reflection::ExtentInfo* ext = info->extInfo) {
							 if (ext->firstType && ext->secondType && val.IsMap()) {
                VoidPtr p = info->operators.allocator->AssociatePtr(info->operators.allocator->Malloc());
                reflection::CollectionEnumerPtr itor = ext->iterator->Create(p.get());
                uint32 len = val.Size();
								Variant::Pair_T* mp = val.GetMap();
                for (uint32 i = 0; i < len; ++i) {
									itor->Append(Variant::FromValue(std::make_pair(*(mp + i)->key, *(mp + i)->value)));
                }
                return *TBStaticSPCast(p, shared_ptr<T>);
              } else if (ext->firstType && val.IsArray()) {
                VoidPtr p = info->operators.allocator->AssociatePtr(info->operators.allocator->Malloc());
                reflection::CollectionEnumerPtr itor = ext->iterator->Create(p.get());
                uint32 len = val.Size();
								Variant** arr = val.GetArray();
                for (uint32 i = 0; i < len; ++i) {
									itor->Append(**(arr + i));
                }
                return *TBStaticSPCast(p, shared_ptr<T>);
              }
            }
          } else {
						if (typeId == val.TypeId()) {
							return *(reinterpret_cast<T*>(val.DataPtr()));
						} else {
							return *TBDynamicCast(reinterpret_cast<Object*>(val.DataPtr()), T*);
						}
          }
        }
      }
      return T();
    }
  };

	template <typename T> struct
	ToValueImpl<T, typename boost::enable_if<is_smart_ptr<T> >::type> {
		static T Value(const Variant& val) {
			if (val.TypeFlag() == kSharedPtrTypeFlag) {
        T *d = reinterpret_cast<T*>(val.Data());
				return *d;
			} else {
				return make_shared<T::element_type>(val.Value<T::element_type>());
			}
		}
	};

	template <typename _T1, typename _T2>struct
		ToValueImpl < _STD pair<_T1, _T2> > {
		static _STD pair<_T1, _T2> Value(const Variant& val) {
			if (val.IsPair()) {
				return _STD make_pair(val.GetKey()->Value<_T1>(),
					val.GetValue()->Value<_T2>());
			} else if (val.IsMap() && val.Size() > 0) {
				Pair_T* pr = val.AsMapT()->elements;
				return _STD make_pair(pr->key->Value<_T1>(),
					pr->value->Value<_T2>());
			} else {
				return _STD pair<_T1, _T2>();
			}
		}
	};

  template <typename T> struct 
  ToValueImpl<T, typename boost::enable_if<is_arithmetic<T> >::type> {
    static T Value(const Variant& val) {
      switch (val.TypeId()) {
				case Variant::kBoolType: {
						return static_cast<T>(*reinterpret_cast<const bool*>(val.ConstData()));
					}
				case Variant::kInt8Type: {
						return static_cast<T>(*reinterpret_cast<const int8*>(val.ConstData()));
					}
					break;
				case Variant::kUint8Type: {
						return static_cast<T>(*reinterpret_cast<const uint8*>(val.ConstData()));
					}
				case Variant::kInt16Type: {
						return static_cast<T>(*reinterpret_cast<const int16*>(val.ConstData()));
					}
				case Variant::kUint16Type: {
						return static_cast<T>(*reinterpret_cast<const uint16*>(val.ConstData()));
					}
				case Variant::kInt32Type: {
						return static_cast<T>(*reinterpret_cast<const int32*>(val.ConstData()));
					}
				case Variant::kEnumType: 
				case Variant::kUint32Type: {
						return static_cast<T>(*reinterpret_cast<const uint32*>(val.ConstData()));
					}
				case Variant::kInt64Type:
				case Variant::kDurationType:
				case Variant::kDatetimeType:{
						return static_cast<T>(*reinterpret_cast<const int64*>(val.ConstData()));
					}
				case Variant::kUint64Type: {
						return static_cast<T>(*reinterpret_cast<const uint64*>(val.ConstData()));
					}
				case Variant::kFloatType: {
						return static_cast<T>(*reinterpret_cast<const float*>(val.ConstData()));
					}
				case Variant::kDoubleType: {
						return static_cast<T>(*reinterpret_cast<const double*>(val.ConstData()));
					}
      }
      return T();
    }
  };

	template <typename T> struct
	ToValueImpl < T, typename boost::enable_if<is_enum<T> >::type > {
		static T Value(const Variant& val) {
			return static_cast<T>(val.Value<uint32>());
		}
	};

  template <typename T> 
  T Value() const {
    return ToValueImpl<T>::Value(*this);
  }

	template <>
	Variant Value() const {
		return *this;
	}

	template <>
	DateTime Value() const {
		return DateTime(this->Value<int64>());
	};

	template <>
	Duration Value() const {
		return Duration(this->Value<int64>());
	};

	template <> 
	UniqueId Value() const {
		if (kObjectIdType == data_.typeId) {
			return *reinterpret_cast<UniqueId*>(Data());
		} else if (kStringType == data_.typeId) {
			return UniqueId(std::string(AsStringT()->str, AsStringT()->size));
		} else {
			return UniqueId();
		}
	};

	template <>
	_STD string Value() const {
		if (kStringType == data_.typeId) {
			return _STD string(AsStringT()->str, AsStringT()->size);
		} else {
			return _STD string();
		}
	};

	template <>
	string16 Value() const {
		if (kStringType == data_.typeId) {
			return UTF8ToUTF16(_STD string(AsStringT()->str, AsStringT()->size));
		} else {
			return string16();
		}
	};

	template <typename T>
	static Variant RefValue(const T& val) {
		uint32 typeId = GetVariantTypeId<T>(&val);
		Variant v(typeId, kReferenceTypeFlag, kNullDataFlag);
		v.AsObjectT()->obj = const_cast<void*>(static_cast<const void*>(&val));
		return v;
	}

	template <typename T>
	static Variant RefValue(const shared_ptr<T>& val) {
		uint32 typeId = GetVariantTypeId<T>(val.get());
		TB_ASSERT(TB_VALID_TYPE(typeId));
		Variant v(typeId, kRefSharedPtrTypeFlag, kNullDataFlag);
		v.AsObjectT()->obj = const_cast<void*>(static_cast<const void*>(&val));
		return v;
	}

  template <typename T> 
  T* UnRef() const {
    TB_ASSERT(kReferenceTypeFlag == data_.typeFlag);
    return reinterpret_cast<T*>(AsObjectT()->obj);
  }

  static const uint32 kBuildinTypeSize = kDatetimeType - kNullType;
	static bool IsBuildinTypeId(uint32 typeId) { return typeId > kNullType && typeId <= kObjectIdType; }
  static bool IsSimpleTypeId(uint32 typeId) { return typeId > kNullType && typeId <= kDoubleType; }
  static bool IsUserTypeId(uint32 typeId) { return typeId > kUserType; }

 public:
	struct ObjectId_T {
		UniqueId* oid;
	};

  struct String_T {
    char* str;
    uint32 size;
  };

  struct Object_T {
    void* obj;
    reflection::Allocator* alloc;
  };

  struct Pair_T {
    Variant* key;
    Variant* value;
  };

  struct Map_T {
    Pair_T* elements;
    uint32 size;
    uint32 capacity;
  };

  struct Array_T {
    Variant** elements;
    uint32 size;
    uint32 capacity;
  };

  union Number_T {
#if defined(TB_ARCH_ENDIAN_LITTLE)
    struct {
      int8 i8;
      char padding[7];
    } i8;

    struct {
      uint8 u8;
      char padding[7];
    } u8;

    struct {
      int16 i16;
      char padding[6];
    } i16;

    struct {
      uint16 u16;
      char padding[6];
    } u16;

    struct {
      int32 i32;
      char padding[4];
    } i32;

    struct {
      uint32 u32;
      char padding[4];
    } u32;

    struct {
      float f;
      char padding[4];
    } f;
#else
    struct {
      char padding[7];
      int8 i8;
    } i8;

    struct {
      uint8 u8;
      char padding[7];
    } u8;

    struct {
      char padding[6];
      int16 i16;
    } i16;

    struct {
      char padding[6];
      uint16 u16;
    } u16;

    struct {
      char padding[4];
      int32 i32;
    } i32;

    struct {
      char padding[4];
      uint32 u32;
    } u32;

    struct {
      char padding[4];
      float f;
    } f;
#endif
    int64 i64;
    uint64 u64;
    double d;
  };

private:
  struct Data_T {
    union Value_T {
			void* ptr;
			Number_T num;
    } value;
    std::shared_ptr<boost::atomic_int> refCount;
		uint32 typeFlag : 3;
		uint32 dataFlag : 3;
    uint32 typeId		: 25;
    uint32 isShared : 1;
  } data_; 

	TB_FORCEINLINE ObjectId_T* AsObjectIdT() const {
		return reinterpret_cast<ObjectId_T*>(data_.value.ptr);
	};

	TB_FORCEINLINE String_T* AsStringT() const {
		return reinterpret_cast<String_T*>(data_.value.ptr);
	}

	TB_FORCEINLINE Object_T* AsObjectT() const {
		return reinterpret_cast<Object_T*>(data_.value.ptr);
	}

	TB_FORCEINLINE Pair_T* AsPairT() const {
		return reinterpret_cast<Pair_T*>(data_.value.ptr);
	}

	TB_FORCEINLINE Map_T* AsMapT() const {
		return reinterpret_cast<Map_T*>(data_.value.ptr);
	}

	TB_FORCEINLINE Array_T* AsArrayT() const {
		return reinterpret_cast<Array_T*>(data_.value.ptr);
	}

  Object_T InternalCopyObject(const Object_T* src, uint32 typeId) const;
  Pair_T InternalCopyPair(const Pair_T* src) const;
  Map_T InternalCopyMap(const Map_T* src) const;
  Array_T InternalCopyArray(const Array_T* src) const;
	String_T InternalCopyString(const String_T* src) const;
	ObjectId_T InternalCopyObjectId(const ObjectId_T* src) const;
};

MSVC_POP_WARNING()

template <typename T>
struct VariantTrait<T, typename enable_if<is_enum<T>::value >::type> {
  enum { reflection_id = Variant::kEnumType };
  static uint32 Default() { return TB_UINT32(0); }
};

template <>
struct VariantTrait < Variant > {
	enum { VariantId = Variant::kVariantType };
	static bool Default() { return true; }
};

template <>
struct VariantTrait<void> {
  enum { VariantId = Variant::kNullType };
  static void Default() { }
};

template <>
struct VariantTrait<bool> {
  enum { VariantId = Variant::kBoolType };
  static const char *TypeName() { return "bool";  }
  static bool Default() { return true; }
};

template <>
struct VariantTrait<int8> {
  enum { VariantId = Variant::kInt8Type };
  static const char *TypeName() { return "int8"; }
  static int8 Default() { return TB_INT8(0); }
};

template <>
struct VariantTrait<uint8> {
  enum { VariantId = Variant::kUint8Type };
  static const char *TypeName() { return "uint8"; }
  static uint8 Default() { return TB_UINT8(0); }
};

template <>
struct VariantTrait<int16> {
  enum { VariantId = Variant::kInt16Type };
  static const char *TypeName() { return "int16"; }
  static int16 Default() { return TB_INT16(0); }
};

template <>
struct VariantTrait<uint16> {
  enum { VariantId = Variant::kUint16Type };
  static const char *TypeName() { return "uint16"; }
  static uint16 Default() { return TB_UINT16(0); }
};

template <>
struct VariantTrait<int32> {
  enum { VariantId = Variant::kInt32Type };
  static const char *TypeName() { return "int32"; }
  static int32 Default() { return TB_INT32(0); }
};

template <>
struct VariantTrait<uint32> {
  enum { VariantId = Variant::kUint32Type };
  static const char *TypeName() { return "uint32"; }
  static uint32 Default() { return TB_UINT32(0); }
};

template <>
struct VariantTrait<int64> {
  enum { VariantId = Variant::kInt64Type };
  static const char *TypeName() { return "int64"; }
  static int64 Default() { return TB_INT64(0); }
};

template <>
struct VariantTrait<uint64> {
  enum { VariantId = Variant::kUint64Type };
  static const char *TypeName() { return "uint64"; }
  static uint64 Default() { return TB_UINT64(0); }
};

template <>
struct VariantTrait<float> {
  enum { VariantId = Variant::kFloatType };
  static const char *TypeName() { return "float"; }
  static float Default() { return 0.0f; }
};

template <>
struct VariantTrait<double> {
  enum { VariantId = Variant::kDoubleType };
  static const char *TypeName() { return "double"; }
  static double Default() { return 0.0; }
};

template <>
struct VariantTrait<_STD string> {
  enum { VariantId = Variant::kStringType };
  static const char *TypeName() { return "string"; }
	static  _STD string Default() { return _STD string(); }
};

template <>
struct VariantTrait < string16 > {
	enum { VariantId = Variant::kStringType };
  static const char *TypeName() { return "string"; }
	static string16 Default() { return string16(); }
};

template <>
struct VariantTrait<Duration> {
  enum { VariantId = Variant::kDurationType };
  static const char *TypeName() { return "duration"; }
  static Duration Default() { return Duration(); }
};

template <>
struct VariantTrait<DateTime> {
  enum { VariantId = Variant::kDatetimeType };
  static const char *TypeName() { return "datetime"; }
  static DateTime Default() { return DateTime(); }
};

template <>
struct VariantTrait<UniqueId> {
	enum { VariantId = Variant::kObjectIdType };
  static const char *TypeName() { return "objectid"; }
	static DateTime Default() { return DateTime(); }
};

TB_NAMESPACE_END

#endif //TB_REFLECTION_VARIANT_HPP__
